1   /*
2    * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  /* @test
27     @summary Test SoftChannel program and bank change */
28  
29  import java.io.IOException;
30  
31  import javax.sound.midi.*;
32  import javax.sound.sampled.*;
33  
34  import com.sun.media.sound.*;
35  
36  public class ProgramAndBankChange {
37  
38      private static SimpleInstrument generateTestInstrument(Patch patch) {
39          ModelOscillator osc = new ModelOscillator() {
40              public float getAttenuation() {
41                  return 0;
42              }
43  
44              public int getChannels() {
45                  return 1;
46              }
47  
48              public ModelOscillatorStream open(float samplerate) {
49                  return new ModelOscillatorStream() {
50                      public void close() throws IOException {
51                      }
52  
53                      public void noteOff(int velocity) {
54                      }
55  
56                      public void noteOn(MidiChannel channel, VoiceStatus voice,
57                              int noteNumber, int velocity) {
58                      }
59  
60                      public int read(float[][] buffer, int offset, int len)
61                              throws IOException {
62                          return len;
63                      }
64  
65                      public void setPitch(float ipitch) {
66                      }
67                  };
68              }
69          };
70          ModelPerformer performer = new ModelPerformer();
71          performer.getOscillators().add(osc);
72          SimpleInstrument testinstrument = new SimpleInstrument();
73          testinstrument.setPatch(patch);
74          testinstrument.add(performer);
75          return testinstrument;
76      }
77  
78      private static void assertTrue(boolean value) throws Exception {
79          if (!value)
80              throw new RuntimeException("assertTrue fails!");
81      }
82  
83      private static void testProgramAndBank(SoftSynthesizer soft,
84              AudioInputStream stream, Patch patch) throws Exception {
85  
86          int program = patch.getProgram();
87          int bank = patch.getBank();
88  
89          MidiChannel channel = soft.getChannels()[0];
90          byte[] buff = new byte[2048];
91  
92          channel.programChange(bank, program);
93          channel.noteOn(64, 64);
94          stream.read(buff, 0, buff.length);
95  
96          int foundprogram = -1;
97          int foundbank = -1;
98          VoiceStatus[] vstatus = soft.getVoiceStatus();
99          for (int i = 0; i < vstatus.length; i++) {
100             if (vstatus[i].active) {
101                 foundprogram = vstatus[i].program;
102                 foundbank = vstatus[i].bank;
103                 break;
104             }
105         }
106 
107         assertTrue(foundprogram == program);
108         assertTrue(foundbank == bank);
109 
110         channel.noteOn(64, 0);
111         stream.read(buff, 0, buff.length);
112 
113         channel = soft.getChannels()[1];
114         // Send MSB Bank
115         channel.controlChange(0x00, bank / 128);
116         // Send LSB Bank
117         channel.controlChange(0x20, bank % 128);
118         // Send Program Change
119         channel.programChange(program);
120         channel.noteOn(64, 64);
121         stream.read(buff, 0, buff.length);
122 
123         foundprogram = -1;
124         foundbank = -1;
125         vstatus = soft.getVoiceStatus();
126         for (int i = 0; i < vstatus.length; i++) {
127             if (vstatus[i].active) {
128                 foundprogram = vstatus[i].program;
129                 foundbank = vstatus[i].bank;
130                 break;
131             }
132         }
133         assertTrue(foundprogram == program);
134         assertTrue(foundbank == bank);
135         channel.noteOn(64, 0);
136         stream.read(buff, 0, buff.length);
137     }
138 
139     public static void main(String[] args) throws Exception {
140         SoftSynthesizer soft = new SoftSynthesizer();
141         AudioInputStream stream = soft.openStream(null, null);
142         soft.unloadAllInstruments(soft.getDefaultSoundbank());
143 
144         soft.loadInstrument(generateTestInstrument(new Patch(0, 0)));
145         soft.loadInstrument(generateTestInstrument(new Patch(7, 0)));
146         soft.loadInstrument(generateTestInstrument(new Patch(20, 10)));
147         soft.loadInstrument(generateTestInstrument(new Patch(3678, 15)));
148         soft.loadInstrument(generateTestInstrument(new Patch(4678, 15)));
149 
150         testProgramAndBank(soft, stream, new Patch(0, 0));
151         testProgramAndBank(soft, stream, new Patch(7, 0));
152         testProgramAndBank(soft, stream, new Patch(20, 10));
153         testProgramAndBank(soft, stream, new Patch(3678, 15));
154         testProgramAndBank(soft, stream, new Patch(4678, 15));
155 
156         soft.close();
157     }
158 }